/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.conversion;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 15.07.2007
 * 
 * @author Lin Li
 */
abstract class ChangeType<T> implements Changer<T> {

  public static abstract class SingleChanger<S> {

    private Class<?> type;

    public SingleChanger(Class<?> c) {
      this.type = c;
    }

    public abstract S change(Object data);

    public Class<?> getFromClass() {
      return type;
    }
  }

  private T defaultValue;
  private Class<T> type;

  public ChangeType(Class<T> type, T defaultValue) {
    this.defaultValue = defaultValue;
    this.type = type;
  }

  public abstract SingleChanger<T>[] getchangers();

  public Class<T> getType() {
    return type;
  }

  public T getDefaultValue() {
    return this.defaultValue;
  }

  @SuppressWarnings("unchecked")
  public SingleChanger<T> getConvertFrom(Class<?> c) {
    SingleChanger<T>[] changers = getchangers();
    for (int i = 0; i < changers.length; i++) {
      if (changers[i].getFromClass().equals(c)) return (SingleChanger<T>) changers[i];
    }
    return null;
  }

  public T get(Object o) {
    SingleChanger<T> c = getConvertFrom(o.getClass());
    if (c == null) { 
      throw new Error("No conversion from " + o.getClass().getName() + " to "
                + getType().getName()); 
    }
    return c.change(o);
  }

  public Class<?>[] sourceTypes() {
    SingleChanger<T>[] changers = getchangers();
    Class<?>[] c = new Class<?>[changers.length];
    for (int i = 0; i < changers.length; i++) {
      c[i] = changers[i].getClass();
    }
    return c;
  }
}